package com.ruoyi.project.system.role.service;

import com.google.common.collect.Maps;
import com.ruoyi.common.constant.IAMConstants;
import com.ruoyi.common.exception.IAMException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.project.system.config.service.IConfigService;
import com.ruoyi.project.system.dept.domain.Dept;
import com.ruoyi.project.system.dept.service.IDeptService;
import com.ruoyi.project.system.menu.domain.Menu;
import com.ruoyi.project.system.menu.service.IMenuService;
import com.ruoyi.project.system.role.domain.Role;
import com.ruoyi.project.system.role.domain.RoleMenu;
import com.ruoyi.project.system.role.domain.sync.*;
import com.ruoyi.project.system.third.domain.Third;
import com.ruoyi.project.system.third.service.ThirdService;
import com.ruoyi.project.system.user.domain.User;
import com.ruoyi.project.system.user.service.IUserService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author renzhihao
 * @date 2023/12/08 18:06
 */
@Service
public class SyncService {
    private static final Logger log = LoggerFactory.getLogger(SyncService.class);

    @Autowired
    private IUserService userService;
    @Autowired
    private IConfigService configService;
    @Autowired
    private IDeptService deptService;
    @Autowired
    private IMenuService menuService;
    @Autowired
    private IRoleService roleService;
    @Autowired
    private ThirdService thirdService;

    public void syncRole(List<IAMRole> iamRoleList) {
        List<IAMRole> fullList = iamRoleList.stream().filter(iamRole -> Objects.equals(iamRole.getSyncType(), 0)).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(fullList)) {
            List<Role> roles = roleService.selectRoleList(new Role());
            Map<String, IAMRole> roleMap = fullList.stream().collect(Collectors.toMap(IAMRole::getKey, Function.identity()));
            Map<String, Role> map = roles.stream().filter(role -> roleMap.containsKey(role.getRoleKey()))
                    .collect(Collectors.toMap(Role::getRoleKey, Function.identity()));

            List<Role> addList = Lists.newArrayList();
            List<Role> updateList = Lists.newArrayList();
            List<Role> delList = roles.stream().filter(role -> !roleMap.containsKey(role.getRoleKey())).collect(Collectors.toList());

            for (IAMRole iamRole : fullList) {
                Role curRole = map.get(iamRole.getKey());

                boolean isAdd = false;
                if (curRole == null) {
                    curRole = new Role();
                    curRole.setCreateBy("iam");
                    isAdd = true;
                } else {
                    curRole.setUpdateBy("iam");
                }

                curRole.setRoleName(iamRole.getName());
                curRole.setRoleKey(iamRole.getKey());
                curRole.setRemark(iamRole.getDesc());
                curRole.setStatus("0");

                if (isAdd) {
                    log.info("全量新增角色: {}", curRole);
                    addList.add(curRole);
                } else {
                    log.info("全量编辑角色: {}", curRole);
                    updateList.add(curRole);
                }

                for (Role role : addList) {
                    roleService.insertSyncRole(role);
                }

                for (Role role : updateList) {
                    roleService.updateSyncRole(role);
                }

                for (Role role : delList) {
                    log.info("全量删除角色: {}", curRole);
                    roleService.deleteRoleById(role.getRoleId());
                }
            }
        }

        List<IAMRole> incrementList = iamRoleList.stream().filter(iamRole -> Objects.equals(iamRole.getSyncType(), 1)).collect(Collectors.toList());
        for (IAMRole iamRole : incrementList) {
            Role search = roleService.selectRoleByKey(iamRole.getKey());
            if (Objects.equals(iamRole.getStatus(), 1)) { // 删除
                if (search != null) {
                    log.info("增量删除角色: {}", search);
                    roleService.deleteRoleById(search.getRoleId());
                }
                break;
            }

            Role role = new Role();
            role.setRoleName(iamRole.getName());
            role.setRoleKey(iamRole.getKey());
            role.setRemark(iamRole.getDesc());
            if (search == null) {
                role.setStatus("0");
                role.setRoleSort("1");
                role.setCreateBy("iam");
                roleService.insertSyncRole(role);
                log.info("增量新增角色: {}", role);
            } else {
                role.setRoleId(search.getRoleId());
                role.setUpdateBy("iam");
                roleService.updateSyncRole(role);
                log.info("增量编辑角色: {}, 原数据：{}", role, search);
            }
        }

    }

    @Transactional
    public void syncPermission(List<IAMPermission> iamPermissionList) {
        List<IAMPermission> fullList = iamPermissionList.stream().filter(iamPermission -> Objects.equals(iamPermission.getSyncType(), 0)).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(fullList)) {
            List<Menu> menus = menuService.selectRecycleMenuList();
            long menuId = menus.stream().map(Menu::getMenuId).max(Long::compareTo).orElse(0L) + 1;
            Map<String, IAMPermission> permissionMap = fullList.stream().collect(Collectors.toMap(IAMPermission::getKey, Function.identity()));
            List<Menu> addList = Lists.newArrayList();
            List<Menu> updateList = Lists.newArrayList();
            List<Menu> delList = menus.stream().filter(menu -> !permissionMap.containsKey(menu.getPerms())).collect(Collectors.toList());
            Map<String, Menu> map = menus.stream().filter(menu -> permissionMap.containsKey(menu.getPerms()))
                    .collect(Collectors.toMap(Menu::getPerms, Function.identity()));

            for (IAMPermission iamPermission : fullList) {
                Menu curMenu = map.get(iamPermission.getKey());

                boolean isAdd = false;
                Menu menu = new Menu();
                if (curMenu == null) {
                    menu.setMenuId(menuId++);
                    menu.setCreateBy("iam");
                    isAdd = true;
                } else {
                    menu.setMenuId(menuId);
                    menu.setUpdateBy("iam");
                }

                menu.setMenuName(iamPermission.getName());
                menu.setPerms(iamPermission.getKey());
                menu.setRemark(iamPermission.getDesc());
                if (StringUtils.isNotEmpty(iamPermission.getParentKey())) {
                    Menu parentMenu = map.get(iamPermission.getParentKey());
                    if (parentMenu == null) {
                        menu.setParentPerms(iamPermission.getParentKey());
                    } else {
                        menu.setParentId(parentMenu.getMenuId());
                    }
                } else {
                    menu.setParentId(0L);
                }

                menu.setMenuType(StringUtils.equals(iamPermission.getModel(), "button") ? "F" :
                        iamPermission.getKey().contains(":") ? "C" : "M");

                if (StringUtils.equals(iamPermission.getModel(), "menu") && iamPermission.getKey().contains(":")) {
                    String url = "/" + iamPermission.getKey().replace(":view", "").replace(":", "/");
                    menu.setUrl(url);
                }

                if (isAdd) {
                    addList.add(menu);
                } else {
                    updateList.add(menu);
                }
            }

            Map<String, Long> addMap = addList.stream().collect(Collectors.toMap(Menu::getPerms, Menu::getMenuId));
            for (Menu menu : addList) {
                if (Objects.isNull(menu.getParentId())) {
                    menu.setParentId(addMap.get(menu.getParentPerms()));
                }
            }

            for (Menu menu : updateList) {
                if (Objects.isNull(menu.getParentId())) {
                    menu.setParentId(addMap.get(menu.getParentPerms()));
                }
            }

            if (addList.stream().anyMatch(menu -> Objects.isNull(menu.getParentId())) ||
                    updateList.stream().anyMatch(menu -> Objects.isNull(menu.getParentId()))) {
                throw new IAMException("菜单数据处理异常");
            }

            for (Menu menu : addList) {
                log.info("全量新增菜单: {}", menu);
                menuService.insertMenu(menu);
            }

            for (Menu menu : updateList) {
                log.info("全量编辑菜单: {}", menu);
                menuService.updateMenu(menu);
            }

            for (Menu menu : delList) {
                log.info("全量删除菜单: {}", menu);
                menuService.deleteMenuById(menu.getMenuId());
            }

        }

        List<IAMPermission> incrementList = iamPermissionList.stream().filter(iamPermission -> Objects.equals(iamPermission.getSyncType(), 1)).collect(Collectors.toList());
        for (IAMPermission iamPermission : incrementList) {
            Menu search = menuService.selectMenuByPerms(iamPermission.getKey());
            if (Objects.equals(iamPermission.getStatus(), 1)) { // 删除
                if (search != null) {
                    log.info("增量删除菜单: {}", search);
                    menuService.deleteMenuById(search.getMenuId());
                }
                break;
            }

            // 增改
            Menu menu = new Menu();
            menu.setMenuName(iamPermission.getName());
            menu.setPerms(iamPermission.getKey());
            menu.setRemark(iamPermission.getDesc());
            if (StringUtils.isNotEmpty(iamPermission.getParentKey())) {
                Menu parentMenu = menuService.selectMenuByPerms(iamPermission.getParentKey());
                if (parentMenu == null) {
                    throw new IAMException("父级菜单未找到");
                }
                menu.setParentId(parentMenu.getMenuId());
            } else {
                menu.setParentId(0L);
            }

            menu.setMenuType(StringUtils.equals(iamPermission.getModel(), "button") ? "F" :
                    iamPermission.getKey().contains(":") ? "C" : "M");

            if (StringUtils.equals(iamPermission.getModel(), "menu") && iamPermission.getKey().contains(":")) {
                String url = "/" + iamPermission.getKey().replace(":view", "").replace(":", "/");
                menu.setUrl(url);
            }

            if (search == null) {
                menu.setCreateBy("iam");
                menuService.insertMenu(menu);
                log.info("增量新增菜单: {}", menu);
            } else {
                menu.setMenuId(search.getMenuId());
                menu.setUpdateBy("iam");
                menuService.updateMenu(menu);
                log.info("增量编辑菜单: {}，原数据: {}", menu, search);
            }
        }
    }

    @Transactional
    public void syncRolePermission(List<IAMRolePermission> iamRolePermissionList) {
        List<IAMRolePermission> fullList = iamRolePermissionList.stream().filter(iamRolePermission -> Objects.equals(iamRolePermission.getSyncType(), 0)).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(fullList)) {
            roleService.clearRoleMenu();
            log.info("全量清除角色菜单关联关系");

            List<Role> roles = roleService.selectRoleList(new Role());
            List<Menu> menus = menuService.selectRecycleMenuList();

            List<RoleMenu> roleMenuList = Lists.newArrayList();

            Map<String, Long> roleKeyMap = roles.stream().collect(Collectors.toMap(Role::getRoleKey, Role::getRoleId));
            Map<String, Long> menuPermsMap = menus.stream().collect(Collectors.toMap(Menu::getPerms, Menu::getMenuId));

            for (IAMRolePermission iamRolePermission : fullList) {
                Long roleId = roleKeyMap.get(iamRolePermission.getRoleKey());
                Long menuId = menuPermsMap.get(iamRolePermission.getPermissionKey());

                if (Objects.isNull(roleId) || Objects.isNull(menuId)) {
                    throw new IAMException("角色或权限未找到");
                }

                RoleMenu roleMenu = new RoleMenu();
                roleMenu.setRoleId(roleId);
                roleMenu.setMenuId(menuId);
                roleMenu.setRoleKey(iamRolePermission.getRoleKey());
                roleMenu.setPerms(iamRolePermission.getPermissionKey());
                roleMenuList.add(roleMenu);
            }

            if (CollectionUtils.isNotEmpty(roleMenuList)) {
                for (RoleMenu roleMenu : roleMenuList) {
                    log.info("全量新增角色菜单关联关系: {}", roleMenu);
                }
                roleService.insertSyncRoleMenu(roleMenuList);
            }
        }


        List<IAMRolePermission> incrementList = iamRolePermissionList.stream().filter(iamRolePermission -> Objects.equals(iamRolePermission.getSyncType(), 1)).collect(Collectors.toList());
        List<RoleMenu> roleMenuList = Lists.newArrayList();
        for (IAMRolePermission iamRolePermission : incrementList) {
            String roleKey = iamRolePermission.getRoleKey();
            String permissionKey = iamRolePermission.getPermissionKey();

            Role role = roleService.selectRoleByKey(roleKey);
            Menu menu = menuService.selectMenuByPerms(permissionKey);

            if (role == null || menu == null) {
                throw new IAMException("角色或菜单不存在");
            }

            RoleMenu search = menuService.selectByRoleIdAndMenuId(role.getRoleId(), menu.getMenuId());
            if (Objects.equals(iamRolePermission.getStatus(), 1)) { // 删除
                if (search != null) {
                    menuService.deleteRoleMenu(search);
                    log.info("增量删除角色菜单关联关系: {}$${}", roleKey, permissionKey);
                }
                break;
            }

            if (search == null) {
                RoleMenu roleMenu = new RoleMenu();
                roleMenu.setRoleId(role.getRoleId());
                roleMenu.setMenuId(menu.getMenuId());
                log.info("增量新增角色菜单关联关系: {}$${}", roleKey, permissionKey);
                roleMenuList.add(roleMenu);
            }
        }

        if (CollectionUtils.isNotEmpty(roleMenuList)) {
            roleService.insertSyncRoleMenu(roleMenuList);
        }
    }

    @Transactional
    public void syncRoleAccount(List<IAMRoleAccount> iamRoleAccountList) {
        List<IAMRoleAccount> fullList = iamRoleAccountList.stream().filter(iamRoleAccount -> Objects.equals(iamRoleAccount.getSyncType(), 0)).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(fullList)) {
            roleService.clearUserRole();
            log.info("全量清除用户角色关联关系");

            Map<String, List<IAMRoleAccount>> roleKeyMap = fullList.stream().collect(Collectors.groupingBy(IAMRoleAccount::getRoleKey));
            for (String roleKey : roleKeyMap.keySet()) {
                Role role = roleService.selectRoleByKey(roleKey);

                if (role == null) {
                    throw new IAMException("角色[" + roleKey + "]不存在，无法建立角色用户管理关系");
                }

                List<User> addUserList = Lists.newArrayList();
                for (IAMRoleAccount iamRoleAccount : roleKeyMap.get(roleKey)) {
                    String account = iamRoleAccount.getAccount();
                    User user = userService.selectUserByLoginName(account);

                    if (user == null) {
                        log.warn("用户[{}]不存在，无法建立角色用户管理关系", account);
                        continue;
                    }

                    addUserList.add(user);
                }

                if (CollectionUtils.isNotEmpty(addUserList)) {
                    String loginNames = addUserList.stream().map(User::getLoginName)
                            .map(String::valueOf).collect(Collectors.joining(","));
                    log.info("全量新增用户角色关联关系: {}$${}", roleKey, loginNames);

                    roleService.insertAuthUsers(role.getRoleId(), addUserList.stream().map(User::getUserId)
                            .map(String::valueOf).collect(Collectors.joining(",")));
                }
            }
        }

        List<IAMRoleAccount> incrementList = iamRoleAccountList.stream().filter(iamRoleAccount -> Objects.equals(iamRoleAccount.getSyncType(), 1)).collect(Collectors.toList());
        Map<String, List<IAMRoleAccount>> roleKeyMap = incrementList.stream().collect(Collectors.groupingBy(IAMRoleAccount::getRoleKey));
        for (String roleKey : roleKeyMap.keySet()) {
            Role role = roleService.selectRoleByKey(roleKey);

            if (role == null) {
                throw new IAMException("角色[" + roleKey + "]不存在，无法建立角色用户管理关系");
            }
            Set<Long> authUserIdSet = userService.selectAuthUserByRoleId(role.getRoleId()).stream().map(User::getUserId).collect(Collectors.toSet());

            List<User> addUserList = Lists.newArrayList();
            List<User> delUserList = Lists.newArrayList();
            for (IAMRoleAccount iamRoleAccount : roleKeyMap.get(roleKey)) {
                String account = iamRoleAccount.getAccount();
                User user = userService.selectUserByLoginName(account);

                if (user == null) {
                    log.warn("用户[{}]不存在，无法建立角色用户管理关系", account);
                    continue;
                }

                Long userId = user.getUserId();
                if (Objects.equals(iamRoleAccount.getStatus(), 1)) { // 删除
                    if (authUserIdSet.contains(userId)) {
                        delUserList.add(user);
                    }
                    break;
                }

                if (!authUserIdSet.contains(userId)) {
                    addUserList.add(user);
                }
            }

            if (CollectionUtils.isNotEmpty(addUserList)) {
                String addLoginNames = addUserList.stream().map(User::getLoginName)
                        .map(String::valueOf).collect(Collectors.joining(","));
                log.info("增量新增用户角色关联关系: {}$${}", roleKey, addLoginNames);
                roleService.insertAuthUsers(role.getRoleId(), addUserList.stream().map(User::getUserId)
                        .map(String::valueOf).collect(Collectors.joining(",")));
            }

            if (CollectionUtils.isNotEmpty(delUserList)) {
                String delLoginNames = delUserList.stream().map(User::getLoginName)
                        .map(String::valueOf).collect(Collectors.joining(","));
                log.info("增量删除用户角色关联关系: {}$${}", roleKey, delLoginNames);
                roleService.deleteAuthUsers(role.getRoleId(), delUserList.stream().map(User::getUserId)
                        .map(String::valueOf).collect(Collectors.joining(",")));
            }
        }
    }

    @Transactional
    public void syncPermissionAccount(List<IAMPermissionAccount> iamPermissionAccountList) {
        List<IAMPermissionAccount> fullList = iamPermissionAccountList.stream().filter(iamPermissionAccount -> Objects.equals(iamPermissionAccount.getSyncType(), 0)).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(fullList)) {
            menuService.clearUserMenu();
            log.info("全量清除用户菜单关联关系");

            Map<String, List<IAMPermissionAccount>> permissionKeyMap = fullList.stream().collect(Collectors.groupingBy(IAMPermissionAccount::getPermissionKey));
            for (String permissionKey : permissionKeyMap.keySet()) {
                Menu menu = menuService.selectMenuByPerms(permissionKey);

                if (menu == null) {
                    throw new IAMException("权限[" + permissionKey + "]不存在，无法建立权限用户管理关系");
                }

                List<User> addUserList = Lists.newArrayList();
                for (IAMPermissionAccount iamPermissionAccount : permissionKeyMap.get(permissionKey)) {
                    String account = iamPermissionAccount.getAccount();
                    User user = userService.selectUserByLoginName(account);

                    if (user == null) {
                        log.warn("用户[{}]不存在，无法建立权限用户管理关系", account);
                        continue;
                    }

                    addUserList.add(user);
                }

                if (CollectionUtils.isNotEmpty(addUserList)) {
                    String loginNames = addUserList.stream().map(User::getLoginName)
                            .map(String::valueOf).collect(Collectors.joining(","));
                    log.info("全量新增用户菜单关联关系: {}$${}", permissionKey, loginNames);
                    menuService.insertAuthUsers(menu.getMenuId(), addUserList.stream().map(User::getUserId)
                            .map(String::valueOf).collect(Collectors.joining(",")));
                }
            }
        }

        List<IAMPermissionAccount> incrementList = iamPermissionAccountList.stream().filter(iamPermissionAccount -> Objects.equals(iamPermissionAccount.getSyncType(), 1)).collect(Collectors.toList());
        Map<String, List<IAMPermissionAccount>> permissionKeyMap = incrementList.stream().collect(Collectors.groupingBy(IAMPermissionAccount::getPermissionKey));
        for (String permissionKey : permissionKeyMap.keySet()) {
            Menu menu = menuService.selectMenuByPerms(permissionKey);

            if (menu == null) {
                throw new IAMException("权限[" + permissionKey + "]不存在，无法建立权限用户管理关系");
            }
            Set<Long> authUserIdSet = userService.selectAuthUserByMenuId(menu.getMenuId()).stream().map(User::getUserId).collect(Collectors.toSet());

            List<User> addUserList = Lists.newArrayList();
            List<User> delUserList = Lists.newArrayList();
            for (IAMPermissionAccount iamPermissionAccount : permissionKeyMap.get(permissionKey)) {
                String account = iamPermissionAccount.getAccount();
                User user = userService.selectUserByLoginName(account);

                if (user == null) {
                    log.warn("用户[{}]不存在，无法建立权限用户管理关系", account);
                    continue;
                }

                Long userId = user.getUserId();
                if (Objects.equals(iamPermissionAccount.getStatus(), 1)) { // 删除
                    if (authUserIdSet.contains(userId)) {
                        delUserList.add(user);
                    }
                    break;
                }

                if (!authUserIdSet.contains(userId)) {
                    addUserList.add(user);
                }
            }

            if (CollectionUtils.isNotEmpty(delUserList)) {
                String delLoginNames = delUserList.stream().map(User::getLoginName)
                        .map(String::valueOf).collect(Collectors.joining(","));
                log.info("增量删除用户菜单关联关系: {}$${}", permissionKey, delLoginNames);
                menuService.deleteAuthUsers(menu.getMenuId(), delUserList.stream().map(User::getUserId)
                        .map(String::valueOf).collect(Collectors.joining(",")));
            }

            if (CollectionUtils.isNotEmpty(addUserList)) {
                String addLoginNames = addUserList.stream().map(User::getLoginName)
                        .map(String::valueOf).collect(Collectors.joining(","));
                log.info("增量新增用户菜单关联关系: {}$${}", permissionKey, addLoginNames);
                menuService.insertAuthUsers(menu.getMenuId(), addUserList.stream().map(User::getUserId)
                        .map(String::valueOf).collect(Collectors.joining(",")));
            }
        }
    }

    @Transactional
    public void syncDept(List<IAMSyncDept> iamSyncDeptList) {
        List<IAMSyncDept> fullList = iamSyncDeptList.stream().filter(iamSyncDept -> Objects.equals(iamSyncDept.getSyncType(), IAMConstants.SYNC_TYPE_FULL)).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(fullList)) {
            List<Dept> depts = deptService.selectRecycleDeptList();
            long deptId = depts.stream().map(Dept::getDeptId).max(Long::compareTo).orElse(0L) + 1;
            Map<String, IAMSyncDept> deptMap = fullList.stream().collect(Collectors.toMap(IAMSyncDept::getDeptNum, Function.identity()));
            List<Dept> addList = Lists.newArrayList();
            List<Dept> updateList = Lists.newArrayList();
            List<Dept> delList = depts.stream().filter(menu -> !deptMap.containsKey(menu.getDeptNum())).collect(Collectors.toList());
            Map<String, Dept> map = depts.stream().filter(menu -> deptMap.containsKey(menu.getDeptNum()))
                    .collect(Collectors.toMap(Dept::getDeptNum, Function.identity()));

            for (IAMSyncDept iamSyncDept : fullList) {
                Dept curDept = map.get(iamSyncDept.getDeptNum());

                boolean isAdd = false;

                Dept dept = new Dept();
                if (curDept == null) {
                    dept.setDeptId(deptId++);
                    dept.setCreateBy("iam");
                    isAdd = true;
                } else {
                    dept.setUpdateBy("iam");
                }

                dept.setDeptName(iamSyncDept.getName());
                dept.setDeptNum(iamSyncDept.getDeptNum());

                if (StringUtils.isNotEmpty(iamSyncDept.getParentNum())) {
                    Dept parentDept = map.get(iamSyncDept.getParentNum());
                    if (parentDept == null) {
                        dept.setParentNum(iamSyncDept.getParentNum());
                    } else {
                        dept.setParentId(parentDept.getDeptId());
                        dept.setAncestors(parentDept.getAncestors() + "," + parentDept.getDeptId());
                    }
                } else {
                    dept.setParentId(0L);
                    dept.setAncestors("0");
                }

                Map<String, Object> attrs = iamSyncDept.getAttrs();
                dept.setLeader((String) attrs.get("leader"));
                dept.setPhone((String) attrs.get("phone"));
                dept.setEmail((String) attrs.get("email"));


                if (isAdd) {
                    addList.add(dept);
                } else {
                    updateList.add(dept);
                }
            }

            Map<String, Dept> addMap = addList.stream().collect(Collectors.toMap(Dept::getDeptNum, Function.identity()));
            for (Dept dept : addList) {
                if (Objects.isNull(dept.getParentId())) {
                    Dept parentDept = addMap.get(dept.getParentNum());
                    if (parentDept != null) {
                        dept.setParentId(parentDept.getParentId());
                        dept.setAncestors(parentDept.getAncestors() + "," + parentDept.getDeptId());
                    }
                }
            }

            for (Dept dept : updateList) {
                if (Objects.isNull(dept.getParentId())) {
                    Dept parentDept = addMap.get(dept.getParentNum());
                    if (parentDept != null) {
                        dept.setParentId(parentDept.getParentId());
                        dept.setAncestors(parentDept.getAncestors() + "," + parentDept.getDeptId());
                    }
                }
            }

            if (addList.stream().anyMatch(dept -> Objects.isNull(dept.getParentId())) ||
                    updateList.stream().anyMatch(dept -> Objects.isNull(dept.getParentId()))) {
                throw new IAMException("部门数据处理异常");
            }

            for (Dept dept : addList) {
                log.info("全量新增部门: {}", dept);
                deptService.insertDept(dept);
            }

            for (Dept dept : updateList) {
                log.info("全量编辑部门: {}", dept);
                deptService.updateDept(dept);
            }

            for (Dept dept : delList) {
                log.info("全量删除部门: {}", dept);
                deptService.deleteDeptById(dept.getDeptId());
            }
        }

        List<IAMSyncDept> incrementList = iamSyncDeptList.stream().filter(iamSyncDept -> !Objects.equals(iamSyncDept.getSyncType(), IAMConstants.SYNC_TYPE_FULL)).collect(Collectors.toList());
        for (IAMSyncDept iamSyncDept : incrementList) {
            String deptNum = iamSyncDept.getDeptNum();
            Dept search = deptService.selectDeptByNum(deptNum);
            if (Objects.equals(iamSyncDept.getSyncType(), IAMConstants.SYNC_TYPE_DEL)) {
                if (search != null) {
                    Long deptId = search.getDeptId();
                    if (deptService.selectDeptCount(deptId) > 0) {
                        throw new IAMException("部门存在子部门,不允许删除");
                    }
                    if (deptService.checkDeptExistUser(deptId)) {
                        throw new IAMException("部门存在用户,不允许删除");
                    }
                    log.info("增量删除部门: {}", search);
                    deptService.deleteDeptById(deptId);
                }
                break;
            }

            String parentNum = iamSyncDept.getParentNum();
            Dept parentDept = deptService.selectDeptByNum(parentNum);

            Map<String, Object> attrs = iamSyncDept.getAttrs();
            Dept dept = new Dept();
            dept.setDeptName(iamSyncDept.getName());
            dept.setDeptNum(iamSyncDept.getDeptNum());
            dept.setStatus(String.valueOf(iamSyncDept.getStatus()));
            dept.setOrderNum(iamSyncDept.getSort());
            if (parentDept == null) {
                dept.setParentId(0L);
                dept.setAncestors("0");
            } else {
                dept.setParentId(parentDept.getDeptId());
                dept.setAncestors(parentDept.getAncestors() + "," + parentDept.getDeptId());
            }

            dept.setLeader((String) attrs.get("leader"));
            dept.setPhone((String) attrs.get("phone"));
            dept.setEmail((String) attrs.get("email"));

            if (search == null) {
                dept.setCreateBy("iam");
                deptService.insertDept(dept);
                log.info("增量新增部门: {}", dept);
            } else {
                deptService.updateDept(dept);
                log.info("增量编辑部门: {}，原数据: {}", dept, search);
            }
        }
    }

    public void syncUser(List<IAMSyncAccount> iamSyncAccountList) {
        String defaultPassword = configService.selectConfigByKey("sys.user.initPassword");
        Third third = thirdService.selectThirdAuth();
        boolean accountSync = Objects.equals(third.getAccountSync(), 0);

        Map<String, Long> menuMap = Maps.newHashMap();
        Map<String, Long> roleMap = Maps.newHashMap();
        if (accountSync) {
            List<Menu> menus = menuService.selectRecycleMenuList();
            List<Role> roles = roleService.selectRoleList(new Role());
            menuMap = menus.stream().collect(Collectors.toMap(Menu::getPerms, Menu::getMenuId));
            roleMap = roles.stream().collect(Collectors.toMap(Role::getRoleKey, Role::getRoleId));
        }


        List<IAMSyncAccount> fullList = iamSyncAccountList.stream().filter(iamSyncAccount -> Objects.equals(iamSyncAccount.getSyncType(), IAMConstants.SYNC_TYPE_FULL)).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(fullList)) {
            List<User> users = userService.selectRecycleUserList();

            Map<String, IAMSyncAccount> accountMap = fullList.stream().collect(Collectors.toMap(IAMSyncAccount::getPrincipalId, Function.identity()));
            Map<String, User> map = users.stream().filter(user -> accountMap.containsKey(user.getLoginName()))
                    .collect(Collectors.toMap(User::getLoginName, Function.identity()));

            List<User> addList = Lists.newArrayList();
            List<User> updateList = Lists.newArrayList();
            List<User> delList = users.stream().filter(user -> !accountMap.containsKey(user.getLoginName())).collect(Collectors.toList());

            for (IAMSyncAccount iamSyncAccount : fullList) {
                String principalId = iamSyncAccount.getPrincipalId();
                User curUser = map.get(principalId);

                String password = iamSyncAccount.getPassword() == null ? defaultPassword : iamSyncAccount.getPassword();
                boolean isAdd = false;

                User user = new User();
                if (curUser == null) {
                    user.setPassword(password);
                    user.setCreateBy("iam");
                    isAdd = true;
                } else {
                    user.setUserId(curUser.getUserId());
                    user.setUpdateBy("iam");
                    if (StringUtils.isNotEmpty(iamSyncAccount.getPassword())) {
                        user.setPassword(iamSyncAccount.getPassword());
                    }
                }

                Map<String, Object> attributes = iamSyncAccount.getAttributes();
                user.setLoginName(principalId);
                user.setUserName((String) attributes.get("userName"));
                user.setPhonenumber((String) attributes.get("phonenumber"));
                user.setEmail((String) attributes.get("email"));
                user.setSex((String) attributes.get("sex"));
                user.setStatus(iamSyncAccount.getStatus());

                List<String> deptNums = iamSyncAccount.getDeptNums();
                if (CollectionUtils.isNotEmpty(deptNums)) {
                    String deptNum = deptNums.get(0);
                    Dept dept = deptService.selectDeptByNum(deptNum);
                    if (dept != null) {
                        user.setDeptId(dept.getDeptId());
                    }
                }

                if (accountSync) {
                    List<String> roleKeys = iamSyncAccount.getAppRoles();
                    List<String> permissionKeys = iamSyncAccount.getAppPermissions();
                    if (CollectionUtils.isNotEmpty(roleKeys)) {
                        Long[] roleIds = roleKeys.stream().map(roleMap::get).filter(Objects::nonNull).toArray(Long[]::new);
                        user.setRoleIds(roleIds);
                    }

                    if (CollectionUtils.isNotEmpty(permissionKeys)) {
                        Long[] menuIds = permissionKeys.stream().map(menuMap::get).filter(Objects::nonNull).toArray(Long[]::new);
                        user.setMenuIds(menuIds);
                    }
                }

                if (isAdd) {
                    log.info("全量新增用户: {}", user);
                    addList.add(user);
                } else {
                    log.info("全量编辑用户: {}", user);
                    updateList.add(user);
                }
            }

            for (User u : addList) {
                userService.insertUser(u);
            }

            for (User u : updateList) {
                if (accountSync) {
                    userService.updateUser(u);
                } else {
                    userService.updateUserInfo(u);
                }

                if (StringUtils.isNotEmpty(u.getPassword())) {
                    userService.resetUserPwd(u);
                }
            }

            for (User u : delList) {
                log.info("全量删除用户: {}", u);
                userService.deleteUserById(u.getUserId());
            }
        }


        List<IAMSyncAccount> incrementList = iamSyncAccountList.stream().filter(iamSyncAccount -> !Objects.equals(iamSyncAccount.getSyncType(), IAMConstants.SYNC_TYPE_FULL)).collect(Collectors.toList());
        for (IAMSyncAccount iamSyncAccount : incrementList) {
            if (Objects.equals(iamSyncAccount.getSyncType(), IAMConstants.SYNC_TYPE_DEL)) {
                String principalId = iamSyncAccount.getPrincipalId();
                User search = userService.selectUserByLoginName(principalId);

                if (search != null) {
                    log.info("增量删除用户: {}", search);
                    userService.deleteUserById(search.getUserId());
                }
                break;
            }

            Map<String, Object> attributes = iamSyncAccount.getAttributes();
            User user = new User();
            String principalId = iamSyncAccount.getPrincipalId();
            String password = iamSyncAccount.getPassword() == null ? defaultPassword : iamSyncAccount.getPassword();
            user.setLoginName(principalId);
            user.setUserName((String) attributes.get("userName"));
            user.setPhonenumber((String) attributes.get("phonenumber"));
            user.setEmail((String) attributes.get("email"));
            user.setSex((String) attributes.get("sex"));
            user.setStatus(iamSyncAccount.getStatus());

            List<String> deptNums = iamSyncAccount.getDeptNums();
            if (CollectionUtils.isNotEmpty(deptNums)) {
                String deptNum = deptNums.get(0);
                Dept dept = deptService.selectDeptByNum(deptNum);
                if (dept != null) {
                    user.setDeptId(dept.getDeptId());
                }
            }

            if (accountSync) {
                List<String> roleKeys = iamSyncAccount.getAppRoles();
                List<String> permissionKeys = iamSyncAccount.getAppPermissions();
                if (CollectionUtils.isNotEmpty(roleKeys)) {
                    Long[] roleIds = roleKeys.stream().map(roleMap::get).filter(Objects::nonNull).toArray(Long[]::new);
                    user.setRoleIds(roleIds);
                }

                if (CollectionUtils.isNotEmpty(permissionKeys)) {
                    Long[] menuIds = permissionKeys.stream().map(menuMap::get).filter(Objects::nonNull).toArray(Long[]::new);
                    user.setMenuIds(menuIds);
                }
            }

            User searchUser = userService.selectUserByLoginName(principalId);
            if (searchUser == null) {
                user.setCreateBy("iam");
                user.setPassword(password);
                userService.insertUser(user);
                log.info("增量新增用户: {}", user);
            } else {
                user.setUpdateBy("iam");
                user.setUserId(searchUser.getUserId());

                if (accountSync) {
                    userService.updateUser(user);
                } else {
                    userService.updateUserInfo(user);
                }

                if (StringUtils.isNotEmpty(iamSyncAccount.getPassword())) {
                    user.setPassword(iamSyncAccount.getPassword());
                    userService.resetUserPwd(user);
                }
                log.info("增量修改用户: {}", user);
            }
        }
    }
}
